/**
 * ReportGear(2011)
 */
package com.reportgear.report.model.script;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.abbp.report.model.ReportModel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.reportgear.report.model.auxiliary.ColumnRow;
import com.reportgear.report.model.script.function.Avg;
import com.reportgear.report.model.script.function.Function;
import com.reportgear.report.model.script.function.FunctionManager;
import com.reportgear.report.model.script.function.Sum;
import com.reportgear.report.model.script.function.ToList;

/**
 * 脚本计算上下文
 * 
 * @version 1.0 2011-4-10
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since ReportGear 1.0
 */
public enum ScriptContext {
	INSTANCE;

	private static final Logger logger = LoggerFactory.getLogger(ScriptContext.class.getName());
	// 函数
	private Map<String, Function> functions;
	// 变量
	private Map<String, Object> variables;
	// 当前计算模型
	private ReportModel model;
	// 表达式计算器
	private Expression expression;
	// 条件表达式计算器
	private ConditionExpression conditionExpression;

	private ScriptContext() {
		this.functions = new HashMap<String, Function>();
		this.variables = new HashMap<String, Object>();

		this.registFunctions();

		this.expression = new Expression();
		this.conditionExpression = new ConditionExpression();
	}

	/**
	 * 设置计算报表
	 * 
	 * @param report
	 */
	public void setCalcReportModel(ReportModel model) {
		this.model = model;
	}

	/**
	 * 获取表达式计算器
	 * 
	 * @return 表达式计算器
	 */
	public Expression getExpression() {
		return expression;
	}

	/**
	 * 获取条件表达式计算器
	 * 
	 * @return 条件表达式计算器
	 */
	public ConditionExpression getConditionExpression() {
		return conditionExpression;
	}

	/**
	 * 获取变量
	 * 
	 * @param name
	 *            变量名称
	 * @return 变量值
	 */
	public Object getVariable(String name) {
		return variables.get(name);
	}

	/**
	 * 设置变量
	 * 
	 * @param name
	 *            变量名称
	 * @param value
	 *            设置值
	 */
	public void setVariable(String name, Object value) {
		variables.remove(name);
		variables.put(name, value);
	}

	/**
	 * 获取单元格值
	 * 
	 * @param columnRow
	 *            单元格行列对象
	 * @return 单元格值
	 */
	public Object getCellValue(String columnRow) {
		return String.valueOf(model.getCellDoubleValue(ColumnRow.valueOf(columnRow)));
	}

	/**
	 * 获取函数值
	 * 
	 * @param name
	 *            函数名
	 * @param args
	 *            参数
	 * @return 参数返回值
	 */
	public Object getFuncValue(String name, List<Object> args) {
		Function fn = this.getFunction(name);

		if (args == null) {
			return fn.exec(null);
		} else {
			return fn.exec(args.toArray());
		}
	}

	/**
	 * 获取函数对象
	 * 
	 * @param name
	 *            名称
	 * @return 函数对象
	 */
	public Function getFunction(String name) {
		Function func = functions.get(name.toLowerCase());

		if (func == null) {
			logger.warn("函数'[" + name + "]'没有注册!");
		}
		return func;
	}

	/**
	 * 注册函数
	 * 
	 * @param func
	 *            函数对象
	 */
	public void registerFunction(Function func) {
		functions.put(func.getName().toLowerCase(), func);
	}

	/**
	 * 注册所有函数
	 */
	private void registFunctions() {
		List<Function> fnList = FunctionManager.INSTANCE.getFunctionList();
		for (Function fn : fnList) {
			this.registerFunction(fn);
		}
	}
}
